home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / RGASM.RAR / ASMCODE.EXE / CHAPT8 / FVIEW.ASM < prev    next >
Encoding:
Assembly Source File  |  1993-05-10  |  49.8 KB  |  1,052 lines

  1. ;
  2. ;       Program FView ( Chapter 8 )
  3. ;
  4.     page    55,132
  5. ;**********************************************************************
  6. ;
  7. ;  The file browsing program.  Version  3.3
  8. ;  Last update:   16/04/93 10:49
  9. ;
  10. ;  Author: A.I.Sopin,   VSU,   Voronezh,  Russia  
  11. ;
  12. ;  Usage:  FVIEW [path]filename
  13. ;
  14. ;  Keys used:
  15. ;
  16. ;  "PgDn"           - scroll by one screen down
  17. ;
  18. ;  "PgUp"           - scroll by one screen up
  19. ;
  20. ;  "Home"           - first screen
  21. ;
  22. ;  "End"            - last screen
  23. ;
  24. ;  ""              - scroll by one line down
  25. ;
  26. ;  ""              - scroll by one line up
  27. ;
  28. ;  "->"              - scroll by one position to the right
  29. ;
  30. ;  "<-"              - scroll by one position to the left
  31. ;
  32. ;  "Ctrl" + "Home"  - to the beginning of the line 
  33. ;
  34. ;  "Esc"            - finish working and return to MS-DOS
  35. ;
  36. ;  23 lines of file are shown on the screen
  37. ;
  38. ;  The MS-DOS disk service (Interrupt 21h) is used
  39. ;
  40. ;**********************************************************************
  41.     NAME FVIEW
  42. ;**********************************************************
  43. ;   MACRO  Definitions
  44. ;**********************************************************
  45. SetCurs MACRO   Row,Column
  46.     mov     ah,2                    ;  function 02h - set cursor
  47.     xor     bh,bh                   ;  video page 0
  48.     mov     dh,&Row                 ;  ROW
  49.     mov     dl,&Column              ;  COLUMN
  50.     int     10h                     ;  BIOS video service
  51.     ENDM
  52. ;  Clear screen and set color
  53. SetCol  MACRO   Row,Column,Leng,Attrib
  54.     mov     al,&Column              ;  initial position for output
  55.     SetCurs Row,al                  ;
  56.     mov     al," "                  ;  AL - character for output
  57.     mov     bl,&Attrib              ;  BL - attribute
  58.     mov     ah,9                    ;  output character and attribute
  59.     xor     bh,bh                   ;  video page 0 is used
  60.     mov     cx,&Leng                ;  number of charcacters to be output
  61.     int     10h                     ;  BIOS video service
  62.     ENDM
  63. ;  Output string onto the screen
  64. OutStr  MACRO   String,Row,Column,Leng
  65.     SetCurs &Row,&Column            ;
  66.     lea     si,&String              ;  DS:SI - address of string for output
  67.     mov     cx,&Leng                ;  maximum length of string
  68.     Call    PUTSTR                  ;  output string
  69.     SetCurs 25,80                   ;
  70.     ENDM
  71. ;-----------------------------------------------------------------------
  72. STAC     SEGMENT STACK
  73.      DW      16 dup (?)
  74. LSTAC    EQU     $
  75. STAC     ENDS
  76. ;-----------------------------------------------------------------------
  77. DATA     SEGMENT  PARA PUBLIC 'DATA'
  78. ES0      DW     0                 ;  segment address for  PSP
  79. ;  Characteristic of the block read
  80. AMEM     LABEL  DWORD             ;  offset + segment address for LDS
  81. OFFMEM   DW     0                 ;  buffer start addres (offset)
  82. SEGMEM   DW     0                 ;  segment address of memory received
  83. SEGSTR   DW     0                 ;  segment address of buffers string
  84. HANDLE   DW     0                 ;  handle value for file to be processed
  85. DX0      DW     0                 ;  high part of file length
  86. AX0      DW     0                 ;  low  part of file length
  87. CXL      DW     0                 ;  offset of last block from file start (high)
  88. DXL      DW     0                 ;  offset of last block from file start (low)
  89. CXF      DW     0                 ;  offset of screen from file start (high)
  90. DXF      DW     0                 ;  offset of screen from file start (low)
  91. ABLOK    DW     0                 ;  address of current byte in filke
  92. Count    DW     0                 ;  length of block read (rest)
  93. DXB      DW     0                 ;  offset of screen beginning in file
  94. LENG0    DW     0                 ;  length of part of previous block
  95.                   ;  on current screen
  96. LENGF    DW     0                 ;  length of file part on screen
  97. NREC     DW     0                 ;  number of records preceeding first shown
  98. ;  Characteristics of screen buffer
  99. ASTR     DW     0                 ;  address of character in string
  100. LMOV     DW     0                 ;  length of string in buffer
  101. ABUF     DW     0                 ;  address of beginning of string BUF0
  102. NSTR     DW     0                 ;  number of filled strings in buffer
  103. DRL0     DW     0                 ;  value of screen shift to the right
  104. ERROP    DW     0                 ;  ERROP > 0 -Error on open
  105. ERR0     DW     0                 ;  error flag (for GetMem); error if not 0
  106. VIDSEG   DW     0                 ;  segment address of video buffer
  107. CGA      DB     0                 ;  CGA indicator, is 1 when CGA active
  108. NB       DB     1                 ;  number of blocks on screen (1 or 2)
  109. EOD      DB     0                 ;  EOD = 1 -EndOfFile indicator
  110. W        label  byte
  111. KbdASCII DB     0
  112. KbdScan  DB     0                                         
  113. VMODE    DB     0                 ;  Original video mode
  114. ;  Texts of information lines on screen and error messages
  115. STR1     DB     " PATH: "
  116. PATH     DB     64 dup (0)
  117. STR25    DB     " Use Keys: PgDn, PgUp, Home, End, "
  118.      DB     24, 44, 32, 25, 44, 32, 26, 44, 32, 27, 44
  119.      DB     " Ctrl+Home,  Esc -Exit", 0
  120. ERR00    DB     ' Not enough  memory !!! (press  Enter) ',0
  121. ERR01    DB     ' File not found !!! (press  Enter) ',0
  122. ERR02    DB     ' Data error !!! (Press  Enter) ',0
  123. DATA     ENDS
  124. ;-----------------------------------------------------------------------
  125. _TEXT   SEGMENT PARA PUBLIC 'CODE'
  126.     ASSUME  CS:_TEXT, DS:DATA, SS:STAC
  127. ;-------------------------------------------------------------------
  128. START:  mov     bx,DS             ;  PSP  segment address
  129.     mov     ax,DATA           ;  data segment basing
  130.     mov     ds,ax             ;  DS points to DATA segment
  131.     mov     ax,STAC           ;  address of STACK segment
  132.     mov     SS,ax             ;  switch to internal satck
  133.     mov     SP,word ptr LSTAC ;  stack size in bytes
  134.     mov     ES0,bx            ;  PSP  segment address
  135. ;  Determining and save the current video mode
  136.     mov     ah,0Fh            ;  function 0Fh - get video mode
  137.     int     10h               ;  BIOS video service call
  138.     mov     VMODE,al          ;  save current video mode
  139. ;  Free memory above the program end
  140.     mov     SEGMEM,0          ;  no memory has been allocated
  141.     mov     bx,ZSEG           ;  program end address
  142.     mov     ax,es             ;  segment address of the program beginning
  143.     sub     bx,ax             ;  memory size needed
  144.     mov     ah,4Ah            ;  DOS function number
  145.     int     21h               ;  free memory
  146.     mov     ERR0,ax           ;  Error Code
  147.     jnc     GetMem            ;  Memory reallocated!
  148.     lea     dx,ERR00          ;  address of error message
  149.     jmp     TypErr
  150. ;  Allocate the maximum memory area for the buffer
  151. GetMem: mov     bx,0FFFh          ;  request memory area of the maximum size
  152.     mov     ah,48h            ;  DOS function number
  153.     int     21h               ;  DOS service call
  154.     jnc     Norm              ;  jump if successful
  155.     int     21h               ;  BX = size of largest available block!
  156.     jnc     Norm              ;  jump if memory allocated
  157.     lea     dx,ERR00          ;  address of error message
  158.     jmp     TypErr            ;  otherwise output error message
  159. ;-------------------------------------------------------------------
  160. Norm:   mov     SEGMEM,ax         ;  AX:0 -segment address of allocated
  161.     xor     ah,ah             ;  function 0 - set video mode
  162.     mov     al,03             ;  80x25  Text
  163.     int     10h               ;  BIOS video service call
  164. ;  Parsing the file name in command line
  165.     mov     ERROP,1           ;  Error on Open
  166.     mov     es,ES0            ;  PSP segment address
  167.     mov     si,81h            ;  address of command line tail
  168.     xor     ch,ch             ;  clear high part
  169.     mov     cl,ES:[80h]       ;  CX - length of command string
  170.     and     cx,cx             ;  no parameters?
  171.     jnz     GetPath           ;  parameters specified
  172.     jmp     ErrMsg            ;  output error message
  173. ;-------------------------------------------------------------------
  174. ;  Skip blanks before file name
  175. GetPath:cmp     byte ptr ES:[si]," " ;  blank?
  176.     ja      M1                   ;  no, take character
  177.     inc     si                   ;  to next character
  178.     loop    GetPath              ;  repeat cycle
  179.     jmp     ErrMsg               ;  Put Error Message
  180. ;  Checking wheter the root directory or disk letter specified
  181. M1:     lea     di,PATH              ;  target for full file name
  182.     cmp     word ptr ES:[si]+1,"\:" ;  root directory?
  183.     je      M7                   ;  full path specified!
  184.     cmp     byte ptr ES:[si]+1,":"  ;  disk letter specified?
  185.     jne     M2                   ;  create full path
  186. ;  Pass drive letter and determine current directory on that drive
  187.     mov     dl,ES:[si]           ;  drive letter from command line
  188.     and     dl,0DFh              ;  uppercase
  189.     mov     PATH,dl              ;  put drive letter
  190.     sub     dl,40h               ;  0 - current, 1 -A ....
  191.     add     si,2                 ;  address of file name in command line
  192.     sub     cx,2                 ;  length of command line tail
  193.     jmp     short M3             ;  put current directory and file name
  194. ;  Create full path (drive letter and direxctory name)
  195. M2:     mov     ah,19h               ;  Get default Disk Number
  196.     int     21h                  ;  DOS service call
  197.     add     al,41h               ;  drive letter
  198.     mov     PATH,al              ;  store drive letter
  199.     xor     dl,dl                ;  DL = 0 - default drive
  200. ;  Determining the current directory
  201. M3:     mov     word ptr PATH+1,'\:' ;  
  202.     push    si                   ;  address of file name in command line
  203.     lea     si,PATH+3            ;  DS:SI point to path string
  204.     mov     ah,47h               ;  Get Current Directory
  205.     int     21h                  ;  DOS service call
  206.     push    cx                   ;  length of name in command line
  207.     mov     cx,64                ;  max ength of name 
  208. ;  Determining end of the directory name read
  209. M4:     cmp     byte ptr DS:[si]," " ;  end of name(ASCIIZ) ?
  210.     jna     M5                   ;
  211.     inc     si                   ;  to next character
  212.     loop    M4                   ;
  213. ;  Insert  "\"  before file name
  214. M5:     cmp     byte ptr DS:[si]-1,"\"  ;  backslash already present?
  215.     je      M6                   ;  yes, do nothing
  216.     mov     byte ptr DS:[si],"\" ;  put "\" before file name
  217.     inc     si                   ;  address of file name in PATH
  218. M6:     mov     di,si                ;  destination
  219.     pop     cx                   ;  length of command line tail
  220.     pop     si                   ;  source (address of command line tail)
  221. ;  Copy filke name from command line
  222. M7:     mov     ds,ES0               ;  PSP segment address
  223.     mov     ax,DATA              ;  data segment
  224.     mov     es,ax                ;  ES points to data segment
  225.     cld                          ;  rigth direction
  226.     rep     movsb                ;  copy file name from command line
  227.     mov     byte ptr ES:[di],0   ;  0 at end of string
  228. ;-----------------------------------------------------------------------
  229. ;  Open the file required for reading
  230. Open:   mov     ax,DATA              ;  address of data segment
  231.     mov     ds,ax                ;  DS points to data segment
  232.     xor     al,al                ;  Read File
  233.     lea     dx,PATH              ;  DS:DX - address of path string
  234.     mov     ah,3Dh               ;  Function 3Dh - Open File
  235.     int     21h                  ;  DOS service call
  236.     jnc     Fsize                ;  O'K !
  237. ;  Output message "File not found" and exit
  238. ErrMsg: mov     ax,DATA              ;  data segment basing
  239.     mov     ds,ax                ;
  240.     lea     dx,ERR01             ;  address of error message
  241.     jmp     TypErr               ;  otherwise output error message
  242. ;  Determining length of file
  243. FSize:  mov     HANDLE,ax         ;  store value of file handle
  244.     mov     ERROP,0           ;  Sucsesful Open
  245.     mov     bx,HANDLE         ;  
  246.     mov     ax,4202h          ;  AL = 2 - position to the end of file
  247.     xor     cx,cx             ;  high part of offset
  248.     xor     dx,dx             ;  low part of offset
  249.     int     21h               ;  DOS service call
  250.     mov     AX0,ax            ;  low part of file length
  251.     mov     DX0,dx            ;  high part of file length
  252. ;  Position for readinfg from the beginning of the file
  253.     mov     bx,HANDLE         ;  
  254.     mov     ax,4200h          ;  AL =0 - count from file beginning
  255.     xor     cx,cx             ;  high part of offset
  256.     xor     dx,dx             ;  low part of offset
  257.     int     21h               ;  DOS service call
  258. ;  Determining an offset of the last block from the biginning of the file
  259.     mov     cx,32768          ;  divisor and multiplier
  260.     mov     ax,AX0            ;
  261.     mov     dx,DX0            ;
  262.     div     cx                ;  AX - result, DX - remainder
  263.     xor     dx,dx             ;  clear high part
  264.     mul     cx                ;  AX - low part, DX - high part
  265.     mov     CXL,dx            ;  high part of offset
  266.     mov     DXL,ax            ;  low part of offset
  267.     mov     DRL0,0            ;  clear shift counter
  268. ;-----------------------------------------------------------------------
  269. ;  Define screen attributes and output information strings
  270. CLRSCR: Call    VIDTYP            ;  determine video adapter type
  271.     SetCol  0,0,80,30h        ;  clear line 1
  272.     SetCol  1,0,80*23,1Bh     ;  clear lines 2-24
  273.     SetCol  24,0,80,30h       ;  clear line 25
  274.     OutStr  STR1,0,0,80       ;  output first line (file name)
  275.     OutStr  STR25,24,0,80     ;  output last line (Help)
  276. ;  Preparing parameters for passing file into video buffer
  277. INIT0:  mov     CXF,0             ;  high part (screen beginning)
  278.     mov     DXF,0             ;  low part (screen end)
  279. INIT1:  mov     NSTR,23           ;  maximum number of screen lines
  280.     mov     ABUF,160          ;  address of first byte of screen buffer
  281.     mov     ASTR,0            ;  address of beginning of buffer string
  282.     mov     LMOV,0            ;  length of buffer string created
  283.     mov     KbdScan,0         ;  clear value of SCAN code read
  284.     mov     ax,SEGMEM         ;  
  285.     add     ax,800h           ;  number of paragraphs in file block
  286.     mov     SEGSTR,ax         ;  new segment address
  287. ;-----------------------------------------------------------------------
  288. ;
  289. ;  Read the records of the input file (32768 bytes)
  290. ;
  291. ;-----------------------------------------------------------------------
  292. READ:   Call    RDBLOK            ;  read block of file (up 32768 bytes
  293.     jnc     EOF1              ;  End of file?
  294.     lea     dx,ERR02          ;  yes - error 2 (data error)
  295.     jmp     TypErr            ;  output error message
  296. ;  Check number of blocks on screen
  297. EOF1:   mov     NB,1              ;  one block on screen
  298.     cmp     KbdScan,50h       ;  SCAN -code   ?
  299.     jne     M8                ;  ordinar processing
  300.     cmp     NSTR,23           ;  second record (screen beginning) ?
  301.     je      M9                ;  check for screen beginning
  302.     jl      M10               ;  not screen beginning - two blocks
  303.     mov     DXB,0             ;  if record is skipped, DXB = 0
  304.     jmp     M11               ;  one block on screen !!!
  305. ;  If one block and screen beginning,  DXB=0
  306. M8:     cmp     ABUF,160          ;  screen beginning ?
  307.     jne     M10               ;  no !!!
  308. M9:     cmp     ASTR,0            ;  beginning of first line?
  309.     jnz     M10               ;  no, this isn't screen beginning !!!
  310.     mov     DXB,0             ;  offset of screen beginning in block
  311.     jmp     M11               ;
  312. M10:    mov     NB,2              ;  two blocks on screen
  313.     cmp     Count,0           ;  no bytes have been read?
  314.     jnz     PUTSCR            ;
  315.     mov     NB,1              ;  one block on screen !!!
  316. ;  If end of file, EOD =1
  317. M11:    cmp     Count,0           ;  no bytes have been read?
  318.     jnz     PUTSCR            ;
  319.     mov     EOD,1             ;  set EndOfFile indicator
  320.     jmp     Next              ;  yes, end of file
  321. ;-----------------------------------------------------------------------
  322. ;
  323. ;  Analyse the block read and create the buffer string
  324. ;
  325. ;-----------------------------------------------------------------------
  326. PUTSCR: cmp     KbdScan,50h       ;  SCAN -code   ?
  327.     jne     PUT1              ;  ordinar processing
  328.     cmp     NSTR,23           ;  second record (screen beginning) ?
  329.     jne     CHAR              ;  ordinar processing
  330.     cmp     ASTR,0            ;  line beginning ?
  331.     jnz     CHAR              ;  no
  332.     jmp     short PUT2        ;  set characteristics of screen beginning
  333. PUT1:   cmp     ABUF,160          ;  screen beginning ?
  334.     jne     CHAR              ;  no
  335.     cmp     ASTR,0            ;  beginning of first line ?
  336.     jnz     CHAR              ;  no
  337. PUT2:   mov     ax,Count          ;  rest of block read
  338.     mov     LENG0,ax          ;  rest of previopus block on screen
  339.     mov     LENGF,0           ;  length of file part for screen
  340. ;  Take and process the current byte from the file (BX)
  341. CHAR:   mov     es,SEGMEM         ;  ES -segment address of block read
  342.     mov     di,ABLOK          ;  source address (offset)
  343.     mov     bx,ES:[DI]        ;  BL - number of current block read
  344.     inc     ABLOK             ;  number of next block
  345.     dec     Count             ;  length of rest of buffer
  346.     mov     es,SEGSTR         ;  segment address of string buffer
  347.     cmp     KbdScan,50h       ;  SCAN -code   ?
  348.     jne     M12               ;  ordinary processing
  349. ;  Correction of file parameters for "" operation
  350.     cmp     NSTR,1            ;  last line ?
  351.     je      M12               ;  ordinary processing fur passing into buffer
  352.     cmp     NSTR,24           ;  first line not to be sent?
  353.     jne     M13               ;  ordinary processing
  354.     inc     DXB               ;  modify offset of first line
  355.     add     DXF,1             ;  offset from file biginning
  356.     adc     CXF,0             ;  high part of offset
  357.     jmp     short M14         ;  while length of file extent = 0
  358. ;  Clear buffer string befor filling the buffer
  359. M12:    cmp     ASTR,0            ;  line biginning?
  360.     jnz     M13               ;
  361.     xor     di,di             ;  ES:[0] -address of line bigiining
  362.     mov     cx,2000           ;  Count of words
  363.     mov     ax,"  "           ;  Character is the Space
  364.     cld                       ;  Clear Direction Flag
  365.     rep     stosw             ;  Clear of Buffer
  366. ;  Processing control characters (Tab, LF, CR)
  367. M13:    inc     LENGF             ;  length of file part on screen
  368. M14:    cmp     bl,09h            ;  Tab ?
  369.     je      HT0               ;
  370.     cmp     bl,0Ah            ;  Line Feed?
  371.     je      LF0               ;
  372.     cmp     bl,0Dh            ;  Carriage Return ?
  373.     je      CRR0              ;
  374. ;  Send text to the buffer string
  375.     mov     di,ASTR           ;  ES:DI - address of byte in buffer string
  376.     mov     ES:[DI],bl        ;  byte read (except control characters)
  377.     inc     ASTR              ;  address of next byte in line
  378.     inc     LMOV              ;  modify length of screen line
  379.     jmp     Next              ;  check for line filled
  380. ;---
  381. ;  Processing of horizontal tabulation (Tab =09h)
  382. HT0:    mov     ax,ASTR           ;  position of the next character
  383.     mov     cl,3              ;  number of shifts for dividing by 8
  384.     shr     ax,cl             ;
  385.     inc     ax                ;  next position 
  386.     mov     cl,3              ;  number of shifts for multiplying
  387.     shl     ax,cl             ;  address of next character
  388.     mov     LMOV,ax           ;  length of string-position of first char
  389.     sub     ax,ASTR           ;  shift character to emulate Tab
  390.     add     ASTR,ax           ;  new position of the character
  391.     jmp     Next              ;  check for line filled
  392. ;---
  393. ;  Processing of Line Feed character  0Ah
  394. LF0:    jmp     Next              ;  check for line filled
  395. ;---
  396. ;  Processing of Carriage Return character 0Dh 
  397. CRR0:   cmp     KbdScan,50h       ;  SCAN -code   ?
  398.     jne     CRR1              ;  ordinar processing
  399.     cmp     NSTR,1            ;  last line ?
  400.     jne     CRR3              ;  don't pass into video buffer!
  401. CRR1:   mov     cx,LMOV           ;  length of line parsed
  402.     sub     cx,DRL0           ;  length for passing (shifted)
  403.     jg      CRR2              ;
  404.     xor     bh,bh             ;  clear next character
  405. ;  Pass the string parsed int the video buffer
  406. CRR2:   mov     di,ABUF           ;  target offset
  407.     mov     si,DRL0           ;  take shift into account
  408.     mov     es,VIDSEG         ;  segment address of video buffer
  409.     mov     ds,SEGSTR         ;  segment address of buffer string
  410.     mov     cx,80             ;  max length of string
  411.     Call    VIDEO             ;  plase string into video buffer
  412. ;  Advance cycle parameters
  413.     mov     ax,DATA           ;  data segment basing
  414.     mov     ds,ax             ;  restore segment address
  415.     add     ABUF,160          ;  address of new line
  416. ;  Check for the presence of the LF character after CR in last line
  417. CRR3:   mov     LMOV,0            ;  length of buffer string
  418.     mov     ASTR,0            ;  address of buffer string beginning
  419.     dec     NSTR              ;  lines left in screen buffer
  420.     cmp     NSTR,23           ;  don't pass thi8s line ?
  421.     jne     CRR4              ;  ordinar processing ?
  422. ;  Process next LF character for line not being passed
  423.     cmp     bh,0Ah            ;  Line Feed ?
  424.     jne     Next              ;
  425.     inc     DXB               ;  modify offset of first line
  426.     add     DXF,1             ;  offset from file beginning
  427.     adc     CXF,0             ;  high part of offset
  428.     jmp     short CRR5        ;
  429. CRR4:   cmp     NSTR,0            ;  all lines processed?
  430.     jnz     Next              ;  not last line
  431.     cmp     bh,0Ah            ;  Line Feed?
  432.     jne     Next              ;
  433. CRR5:   inc     ABLOK             ;  address of next byte
  434.     inc     LENGF             ;  jump over LF character
  435.     dec     Count             ;  length of block's rest
  436. ;-----------------------------------------------------------------------
  437. ;  Check whether the screen has been buffer villed
  438. Next:   cmp     NSTR,0            ;  screen filled ?
  439.     jz      GETKEY            ;  yes, output
  440.     cmp     EOD,1             ;  end of file ?
  441.     je      Next1             ;  output full screen
  442.     cmp     Count,0           ;  all block processed?
  443.     jz      JMP1              ;  yes, read next block
  444.     jmp     PUTSCR            ;  continue to process current block
  445. JMP1:   jmp     READ              ;  read next block
  446. ;  Clear the lower part of the last screen which isn't completely filled 
  447. Next1:  xor     dx,dx             ;  high part of multiplier
  448.     mov     ax,80             ;  multiplier
  449.     mul     NSTR              ;  AX - number of character
  450.     mov     cx,ax             ;
  451.     mov     bx,24             ;  maximum number of lines
  452.     sub     bx,NSTR           ;  BL - number of first line
  453.     SetCol  bl,0,cx,1Bh       ;  clear lower lines
  454.     SetCurs 25,80             ;  hide cursor
  455. ;-----------------------------------------------------------------------
  456. ;  Clear the keyboard buffer and wait for key pressed
  457. GETKEY: mov     ASTR,0              ;  address of buffer string beginning
  458.     mov     LMOV,0              ;  length of buffer string created
  459.     mov     NSTR,23             ;  max number of lines on screen
  460.     mov     ABUF,160            ;  address of first byte of video buffer
  461.     cli                         ;  disable interrupts
  462.     xor     ax,ax               ;  
  463.     mov     ES,ax               ;  ES points to BIOS data segment
  464.     mov     al,ES:[41Ah]        ;  address of keyboard buffer head
  465.     mov     ES:[41Ch],al        ;  clear buffer (tail ptr = head ptr)
  466.     sti                         ;  enable interrupts
  467.     xor     ah,ah               ;  function 0 - Get Key
  468.     int     16h                 ;  BIOS keyboard service
  469.     mov     KbdASCII,al         ;  store ASCII character read
  470.     mov     KbdScan,ah          ;  store SCAN code
  471. ;-----------------------------------------------------------------------
  472. ;
  473. ;  Process the code of a key pressed (Esc -Exit)
  474. ;
  475. ;-----------------------------------------------------------------------
  476. Esc0:   cmp     KbdScan,1         ;  SCAN -code  Esc ?
  477.     jne     PgDn              ;
  478.     jmp     Exit              ;  Return to  MS-DOS
  479. ;-----------------------------------------------------------------------
  480. ;  PgDn - show the next screen
  481. PgDn:   cmp     KbdScan,51h       ;  SCAN -code  PgDn ?
  482.     jne     PgUp              ;
  483.     cmp     EOD,1             ;  end of file ?
  484.     jne     PgDn1             ;  not, create next screen in buffer
  485.     jmp     GETKEY            ;  wait for next key stroke
  486. PgDn1:  Call    NEXTSCR           ;  display next screen
  487.     jmp     Next              ;  continue processing
  488. ;-----------------------------------------------------------------------
  489. ;  PgUp - show the previous screen
  490. PgUp:   cmp     KbdScan,49h       ;  SCAN -code  PgUp ?
  491.     je      PgUp1             ;
  492.     jmp     Home              ;
  493. ;  Form parameters and display the previous screen
  494. PgUp1:  mov     NREC,23           ;  number of lines read backwards
  495.     Call    GOLOW             ;  back to one screen
  496.     mov     NB,1              ;  one block on screen
  497.     mov     EOD,0             ;  clear End IOf File indicator
  498.     jmp     PUTSCR            ;  output screen
  499. ;-----------------------------------------------------------------------
  500. ;  Home - to the beginning of the file
  501. Home:   cmp     KbdScan,47h       ;  SCAN -code  Home ?
  502.     jne     End$              ;
  503.     mov     bx,HANDLE         ;  value of file handle
  504.     mov     ax,4200h          ;  AL = 0 - read file from the beginning
  505.     xor     cx,cx             ;  high part of offset
  506.     xor     dx,dx             ;  low part of offset 
  507.     int     21h               ;  DOS service call
  508.     jmp     INIT0             ;  to the file beginning
  509. ;-----------------------------------------------------------------------
  510. ;  End - show the last screen
  511. End$:   cmp     KbdScan,4Fh       ;  SCAN -code  End ?
  512.     jne     Right             ;
  513.     mov     NB,1              ;  one block on screen
  514.     mov     cx,CXL            ;  high part of offset
  515.     mov     dx,DXL            ;  low part of offset
  516.     mov     CXF,cx            ;  high part (screen beginning)
  517.     mov     DXF,dx            ;  low part (screen beginning)
  518.     Call    POSIT             ;  read block of file
  519. ;  Output last lines of the last block
  520.     mov     EOD,0             ;  clear EndOfFile indicator
  521.     mov     DI,ax             ;  DI - address of last byte + 1
  522.     mov     ES,SEGMEM         ;  ES - segment address of block
  523.     mov     cx,23             ;  number of lines on last screen
  524.     Call    BKREC             ;  find lines
  525.     jnc     End1              ;  lines found!
  526.     xor     dx,dx             ;  accept address of block beginning
  527. ;  Set up parameters for processing the last line
  528. End1:   sub     Count,dx          ;  length of rest of last block
  529.     mov     ABLOK,dx          ;  address of line for processing
  530.     mov     DXB,dx            ;  offset from block beginning
  531.     add     DXF,dx            ;  offset of last line (high)
  532.     adc     CXF,0             ;  offset of last line (low)
  533.     jmp     PUTSCR            ;  output list line
  534. ;-----------------------------------------------------------------------
  535. ;  --->  shift the screen to the right by one position
  536. Right:  cmp     KbdScan,4Dh  ;  SCAN -code  ---> ?
  537.     jne     Left              ;
  538.     inc     DRL0              ;  increase right shift counter
  539.     jmp     Repeat0           ;  repeat screen output
  540. ;-----------------------------------------------------------------------
  541. ;  <---  shift the screen to the left by one position
  542. Left:   cmp     KbdScan,4Bh       ;  SCAN -code  <--- ?
  543.     jne     Low0              ;
  544.     dec     DRL0              ;  decrease right shift counter
  545.     jnl     RpLeft            ;
  546.     mov     DRL0,0            ;  clear shift counter (left position)
  547. RpLeft: jmp     Repeat0           ;  repeat screen output
  548. ;-----------------------------------------------------------------------
  549. ;   - shift the screen content by one position upwards
  550. Low0:   cmp     KbdScan,48h       ;  SCAN -code   ?
  551.     je      Low1              ;  
  552.     jmp     short High0       ;  
  553. ;  Prepare parameters and display the previous line  (AX = LENGR)
  554. Low1:   mov     NREC,1            ;  number of lines processed
  555.     Call    GOLOW             ;  back by one line
  556.     mov     NB,1              ;  one block on screen
  557.     mov     EOD,0             ;  clear EndOfFile indicator
  558.     mov     NSTR,1            ;  output first line only
  559. ;  Screen scrolling downwards by one line
  560.     mov     si,3678           ;  source offset (end of line 22)
  561.     mov     di,3838           ;  target offset (end of line 23)
  562.     mov     ES,VIDSEG         ;  target segment (video buffer)
  563.     mov     DS,VIDSEG         ;  source segment (video buffer)
  564.     mov     cx,22*80          ;  number of words to be scrolled (22lines)
  565.     std                       ;  scroll down
  566.     Call    SCROLL            ;  functional subroutine call
  567.     cld                       ;  Clear Direction Flag
  568.     mov     ax,DATA           ;  DS points to data segment
  569.     mov     ds,ax             ;  restore segment address
  570.     jmp     PUTSCR            ;  output screen 
  571. ;-----------------------------------------------------------------------
  572. ;   - scroll the screen content down by one line
  573. High0:  cmp     KbdScan,50h       ;  SCAN -code   ?
  574.     jne     CtrHom            ;
  575.     cmp     EOD,1             ;  end of file ?
  576.     jne     High1             ;  form next screen
  577.     jmp     GETKEY            ;  repeat screen output
  578. ;  Check whether the next screen is out of file (for "")
  579. High1:  mov     dx,CXF            ;  previous offset (high)
  580.     mov     ax,DXF            ;  previous offset (low))
  581.     add     ax,LENGF          ;  low part of new offset
  582.     adc     dx,0              ;  high part of new offset
  583.     cmp     dx,DX0            ;  offset > length of file ?
  584.     ja      High2             ;  yes, output screen
  585.     jb      High3             ;  high part < length
  586.     cmp     ax,AX0            ;  offset > length of file ?
  587.     jb      High3             ;
  588. High2:  jmp     GETKEY            ;  repeat screen output
  589. ;  Scroll the screen content upward by one line
  590. High3:  mov     NSTR,24           ;  number of lines to be processed
  591.     mov     ABUF,23*160       ;  output into line 23
  592.     mov     si,320            ;  source offset (beginning of line 2)
  593.     mov     di,160            ;  target offset (beginning of line 1)
  594.     mov     ES,VIDSEG         ;  target segment
  595.     mov     DS,VIDSEG         ;  source segment
  596.     mov     cx,22*80          ;  number of words shifted
  597.     cld                       ;  Clear Direct Flag
  598.     Call    SCROLL            ;  screen scrolling subroutine call
  599.     mov     ax,DATA           ;  data segment basing
  600.     mov     ds,ax             ;  restore segment address
  601.     jmp     short Repeat0     ;  position to screen beginning
  602. ;-----------------------------------------------------------------------
  603. ;  Ctrl + Home - display the left part of lines (beginning)
  604. CtrHom: cmp     KbdScan,77h  ;  Ctrl + Home ?
  605.     jne     AnyKey            ;
  606.     mov     DRL0,0            ;  clear shift counter
  607.     jmp     short Repeat0     ;  position to screen beginning
  608. AnyKey: jmp     GETKEY            ;  repeat screen ouputting
  609. ;-----------------------------------------------------------------------
  610. ;  Repeating of the active screen outputting
  611. Repeat0: mov    EOD,0             ;  clear EndOfFile indicator
  612.      cmp    NB,2              ;  two blocks on screen ?
  613.      jne    REP01             ;  no, one block
  614.      mov    cx,CXF            ;  high part of offset
  615.      mov    dx,DXF            ;  low part of offset
  616. ;  Read previous block (high part of screen)
  617.      mov    DXB,0             ;  DXB =0 -clear block offset
  618.      Call   POSIT             ;  read block
  619.      jmp    PUTSCR            ;  repeat screen outputting
  620. ;  Return to the screen beginning (block has already been read)
  621. REP01:   mov    ax,DXB            ;  offset of first line on screen
  622.      mov    ABLOK,ax          ;  address of first byte on screen
  623.      mov    cx,LENG0          ;  full length of block
  624.      mov    Count,cx          ;  rest of block read
  625.      jmp    PUTSCR            ;  repeat screen output
  626. ;-----------------------------------------------------------------------
  627. ;  Output file processing error message (error code is in the AX register)
  628. TypErr:  mov    ax,DATA           ;  address of data segment
  629.      mov    ds,ax             ;  DX:=data segment address
  630.      mov    si,dx             ;  DS:SI - message strings
  631.      SetCurs 3,0              ;  cursor to line 3 for outputting message
  632.      mov    cx,80             ;  number of characters
  633.      Call   PUTSTR            ;  output string onto screen
  634.      SetCurs 25,80            ;  hide cursor
  635.      mov    dl,07h            ;  Bell
  636.      mov    ah,2              ;  Put Character
  637.      int    21h               ;  DOS service call
  638.      xor    ah,ah             ;  function 0 - Get Key
  639.      int    16h               ;  BIOS keyboard service call
  640. ;-------------------------------------------------------------------
  641. ;  Terminate program and exit to DOS
  642. Exit:   cmp     ERROP,0           ;  Sucsesful Open ?
  643.     jnz     Free              ;  file wasn't open!
  644.     mov     ah,3Eh            ;  Function 3Eh -Close File
  645.     mov     bx,HANDLE         ;  BX - value of file handle
  646.     int     21h               ;  DOS service call
  647. Free:   Call    FREEMAIN          ;  free the memory buffer allocate
  648.     mov     al,VMODE          ;  remember video mode on entry
  649.     xor     ah,ah             ;  function 0 - set video mode
  650.     int     10h               ;  BIOS video service
  651.     mov     ax,0C00h          ;  Clear Keyboard Buffer
  652.     int     21h               ;  DOS service call
  653.     mov     ax,4C00h          ;  function 4Ch - terminate process
  654.     int     21h               ;  DOS service call
  655. ;-----------------------------------------------------------------------
  656. ;
  657. ;  Functional subroutines used
  658. ;
  659. ;-----------------------------------------------------------------------
  660. ;***********************************************************
  661. ;
  662. ;  Subroutine for outputting an ASCIIZ string onto the screen
  663. ;
  664. ;  DS:[SI] - address of string beginning (is output at the cursor position)
  665. ;
  666. ;  CX      - length of the string to be output (maximum 80 bytes)
  667. ;
  668. ;  Attention! Before using this subroutine set the cursor location
  669. ;
  670. ;***********************************************************
  671. PUTSTR   PROC   NEAR
  672.      cld                    ;  Clear Direct flag
  673.      xor    bh,bh           ;  video page 0 
  674.      mov    ah,0Eh          ;  function 0Eh - output in teletype mode
  675. PUTS1:   lodsb                  ;  load a byte from the string
  676.      and    al,al           ;  end of line?
  677.      jz     PUTS2           ;  yes, return to caller
  678.      int    10h             ;  BIOS video service
  679.      loop   PUTS1           ;  next performance of cycle
  680. PUTS2:   RETN                   ;  Exit
  681. PUTSTR   ENDP
  682. ;***********************************************************
  683. ;
  684. ;  Free the memory buffer allocated
  685. ;
  686. ;***********************************************************
  687. FREEMAIN PROC   NEAR
  688.      mov    ax,SEGMEM         ;  memory segment address
  689.      and    ax,ax             ;  memory allocated ?
  690.      jnz    Fremem            ;  yes !!!
  691.      jmp    short Freret      ;
  692. Fremem:  mov    ERR0,0            ;  clear error code
  693.      mov    es,ax             ;  memory segment address
  694.      mov    ah,49h            ;  free memory function code
  695.      int    21h               ;  DOS service call
  696.      jnc    Freret            ;
  697.      lea    dx,ERR00          ;  free memory error code
  698.      jmp    TypErr            ;  error message output
  699. Freret:  RETN
  700. FREEMAIN ENDP
  701. ;***********************************************************
  702. ;
  703. ;  Determining the type of the video adapter
  704. ;
  705. ;  CGA = 1 - the CGA card is used
  706. ;
  707. ;  VIDSEG -segment address of the video buffer
  708. ;
  709. ;***********************************************************
  710. VIDTYP  PROC    NEAR
  711.     mov     VIDSEG,0B000h       ;  address of video buffer for MDA
  712.     mov     CGA,0               ;  clear CGA indicator
  713.     mov     ax,40h              ;  segment address of BIOS data area
  714.     mov     ES,ax               ;  ES points to BIOS data area
  715.     mov     al,ES:[10h]         ;  read equipment list
  716.     and     al,30h              ;  clear unused bits
  717.     cmp     al,30h              ;  MDA card ?
  718.     je      VIDRET              ;  yes !
  719. ;  Find an active color card:  EGA (VGA)
  720.     mov     VIDSEG,0B800h           ;  address of color adapter buffer
  721.     mov     CGA,1                   ;  set CGA indicator
  722.     cmp     byte ptr ES:[87h],0     ;  EGA present?
  723.     jz      VIDRET                  ;  EGA  not installed
  724.     test    byte ptr ES:[87h],08h   ;  EGA  active?
  725.     jnz     VIDRET                  ;  bit 3 = 1 - EGA  not active
  726.     mov     CGA,0                   ;  clear CGA indicator
  727. VIDRET: RETN                            ;  Exit
  728. VIDTYP  ENDP
  729. ;***********************************************************
  730. ;
  731. ;  Subroutine for writing a string into the video buffer
  732. ;
  733. ;  DS:[SI] - address of the string to be output
  734. ;
  735. ;  ES:[DI] - address of the string in the video buffer
  736. ;
  737. ;  CX      - max length of the output string (usually 80 bytes)
  738. ;
  739. ;***********************************************************
  740. VIDEO   PROC    NEAR
  741.     cld                       ;  Clear Direct flag
  742.     cmp     CGA,1             ;  CGA card?
  743.     jne     Cycle3            ;  no, don't check for retrace
  744. ;  Wait for retrace
  745. Cycle0: mov     dx,3DAh           ;  video state register (CGA)
  746. Cycle1: in      al,dx             ;  read state register
  747.     test    al,1              ;  retrace?
  748.     jnz     Cycle1            ;  yes, wait for finish
  749. ;  Check whether it is possible to write into video buffer
  750. Cycle2: in      al,dx             ;  read state register
  751.     test    al,1              ;  rerace (writing allowed)?
  752.     jz      Cycle2            ;  no, check again
  753.     lodsb                     ;  take next character from string
  754.     stosb                     ;  output character into video buffer
  755.     inc     di                ;  skip attribute in video buffer
  756.     loop    Cycle0            ;  next step of outward cycle
  757.     RETN                      ;  Return to caller
  758. ;  Non-CGA video card - direct writing always allowed
  759. Cycle3: lodsb                     ;  take next character from string
  760.     stosb                     ;  output character into video buffer
  761.     inc     di                ;  skip attribute in video buffer
  762.     loop    Cycle3            ;  next step of outward cycle
  763.     RETN                      ;  Return to caller
  764. VIDEO   ENDP
  765. ;***********************************************************
  766. ;
  767. ;  The procedure for screen scrolling
  768. ;
  769. ;  DS:[SI] - address of string to be output
  770. ;
  771. ;  ES:[DI] - address of the string in the video buffer
  772. ;
  773. ;  CX      - number of words to be scrolled
  774. ;
  775. ;  The Direction Flag is used to define the scrolling direction
  776. ;
  777. ;  CLD     - scroll upwards
  778. ;
  779. ;  STD     - scroll downwards
  780. ;
  781. ;***********************************************************
  782. SCROLL  PROC    NEAR
  783.     mov     bl,CGA            ;  take CGA indicator
  784.     cmp     bl,1              ;  CGA card?
  785.     jne     Cycle7            ;  no, don't check for retrace
  786. ;  Wait for retrace
  787. Cycle4: mov     dx,3DAh           ;  video state register (CGA)
  788. Cycle5: in      al,dx             ;  read state register
  789.     test    al,1              ;  retrace?
  790.     jnz     Cycle5            ;  yes, wait for finishing
  791. ;  Check whether it is possible to write into video buffer
  792. Cycle6: in      al,dx             ;  read state register
  793.     test    al,1              ;  rerace (writing allowed)?
  794.     jz      Cycle6            ;  no, check again
  795.     lodsw                     ;  take character and attribute
  796.     stosw                     ;  output character and attribute
  797.     loop    Cycle4            ;  next step of outward cycle
  798.     RETN                      ;  return to caller
  799. ;  Non-CGA video card - direct writing always allowed
  800. Cycle7: rep     movsw             ;  output character and attribute
  801.     RETN                      ;  return to caller
  802. SCROLL  ENDP
  803. ;***********************************************************
  804. ;
  805. ;  Procedure for reading a block of file (up  32768 bytes)
  806. ;
  807. ;  Length of block read is returned in the AX register
  808. ;
  809. ;  CF = 0 - operation comleted succesfully
  810. ;
  811. ;  CF = 1 - error while reading (error code in AX)
  812. ;
  813. ;***********************************************************
  814. RDBLOK  PROC    NEAR
  815.     mov     EOD,0             ;  clear EOF flag
  816.     mov     ABLOK,0           ;  start address of read buffer
  817.     mov     bx,HANDLE         ;  load file handle
  818.     mov     cx,32768          ;  required length of block read
  819.     lds     dx,AMEM           ;  load: DX=0, DS is the segment address
  820.     mov     ah,3Fh            ;  function 3Fh - read file with handle
  821.     int     21h               ;  DOS service call
  822.     mov     dx,DATA           ;  data segment address
  823.     mov     ds,dx             ;  restore the segment register
  824.     mov     Count,ax          ;  actual length of block read
  825.     RETN                      ;  Exit
  826. RDBLOK  ENDP
  827. ;***********************************************************
  828. ;
  829. ;  Procedure for positionong and reading the block of file
  830. ;
  831. ;  The DX:CX registers - offset from the beginning of the file
  832. ;
  833. ;  The length of the block read is returned in the AX register
  834. ;
  835. ;  CF = 0 - successful finish
  836. ;
  837. ;  CF =1 - error reading file (error code in AX)
  838. ;
  839. ;***********************************************************
  840. POSIT   PROC   NEAR
  841.     mov     bx,HANDLE         ;  load file handle
  842.     mov     ax,4200h          ;  AL = 0 - read from beginning of file
  843.     int     21h               ;  DOS service call
  844.     Call    RDBLOK            ;  read privious block
  845.     mov     NB,1              ;  one block on screen!
  846.     RETN                      ;  Exit
  847. POSIT   ENDP
  848. ;***********************************************************
  849. ;
  850. ;  Procedure for calculating parameter for outputting the next screen 
  851. ;
  852. ;  CXF, DXF - offset of the current screen from the file beginning
  853. ;
  854. ;  DXB      - offset of the screen start from the block beginning
  855. ;
  856. ;  LENGF    - length of the file part currently shown
  857. ;
  858. ;  LENG0    - length of the rest of previous block on screen
  859. ;
  860. ;***********************************************************
  861. NEXTSCR  PROC   NEAR
  862.      mov    cx,CXF            ;  previous offset (high)
  863.      mov    dx,DXF            ;  previous offset (low)
  864.      add    dx,LENGF          ;  low part of new offset
  865.      adc    cx,0              ;  high part of new offset
  866. ;  Check whether the next screen is out of file
  867.      cmp    cx,DX0            ;  offset > length of file ?
  868.      ja     NXT1              ;  out of file
  869.      jb     NTX2              ;  high part < length
  870.      cmp    dx,AX0            ;  offset > length of file ?
  871.      jb     NTX2              ;
  872. NXT1:    add    sp,2              ;  adjust stack
  873.      jmp    GETKEY            ;  display screen
  874. ;  Check the number of blocks on the screen (1 or 2)
  875. NTX2:    mov    CXF,cx            ;  new offset (high)
  876.      mov    DXF,dx            ;  new offset (low)
  877.      mov    ax,LENGF          ;  length of file part on screen
  878.      cmp    NB,2              ;  two blocks ?
  879.      jne    NXT3              ;  block has already been read
  880. ;  Change the screen containing two blocks
  881.      sub    ax,LENG0          ;  DXB = LENGF - LENG0
  882.      mov    DXB,ax            ;  new offset from block beginning
  883.      mov    ax,COUNT          ;  length of rest of current block
  884.      mov    LENG0,ax          ;  length of rest of previous block
  885.      mov    NB,1              ;  after screen changed one block is shown
  886.      RETN                     ;  return to caller
  887. ;  Change screen with one block present
  888. NXT3:    add    DXB,ax            ;  DXB = DXB + LENGF
  889.      mov    ax,DXB            ;
  890.      mov    ABLOK,ax          ;  address of first byte on screen
  891.      RETN                     ;  return to caller
  892. NEXTSCR  ENDP
  893. ;***********************************************************
  894. ;
  895. ;  Subroutine for reading file backwards
  896. ;
  897. ;  Is used when processing the PgUp and  "" keys
  898. ;
  899. ;  NREC      - number of lines read backwards
  900. ;
  901. ;  NREC = 1  for  "" key
  902. ;
  903. ;  NREC = 23 for  PgUp
  904. ;
  905. ;  Returned values:
  906. ;
  907. ;  DX = ABLOK  - address of first line to be displayed
  908. ;
  909. ;  CXF, DXF    - offset of the first line on the screen from the file beginning
  910. ;
  911. ;  DXB         - offset screen beginning from the block beginning
  912. ;
  913. ;  Count       - length of rest of file shown on the high part of the screen
  914. ;
  915. ;***********************************************************
  916. GOLOW   PROC    NEAR
  917. GOL1:   cmp     DXF,0             ;  file beginning? (low part)
  918.     jnz     GOL2              ;
  919.     cmp     CXF,0             ;  file beginning? (high part)
  920.     jg      GOL2              ;
  921.     add     sp,2              ;  adjust stack
  922.     jmp     GETKEY            ;  repeat screen outputting 
  923. ;  Check how many blocks are on the screen (1 or 2)
  924. GOL2:   cmp     NB,2              ;  two blocks on screen?
  925.     jne     GOL3              ;  no, one
  926.     jmp     GOL7              ;  yes,two
  927. GOL3:   xor     cx,cx             ;  clear LENGR + LENGF
  928.     cmp     DXB,0             ;  block beginning
  929.     jz      GOL4              ;  read previous block
  930. ;======
  931. ;  One block only is shown on the screen and  DXB > 0
  932.     mov     ES,SEGMEM         ;  ES -segment address of block
  933.     mov     di,DXB            ;  ES:DI - address of first line on screen
  934.     mov     cx,NREC           ;  number of lines processed
  935.     Call    BKREC             ;  find previous line
  936.     mov     cx,ax             ;  AX = LRECL - length of line found
  937.     jc      GOL4              ;  line not found
  938.     add     cx,LENGF          ;  CX = LENGR + LENGF
  939.     add     Count,cx          ;  new length of rest of block
  940.     jmp     GOL8              ;  normal return
  941. ;  line to be displayed is on the juncture of blocks (or DXB = 0)
  942. GOL4:   sub     DXF,cx            ;  address of block juncture (high)
  943.     sbb     CXF,0             ;  address of block juncture (low)
  944.     mov     cx,CXF            ;  high part of offset
  945.     mov     dx,DXF            ;  low part of offset
  946.     sub     dx,32768          ;  beginning of previous block (high)
  947.     sbb     cx,0              ;  beginning of previous block (low)
  948.     jl      GOL5              ;  previous block < 32768 bytes
  949. ;  Find first line to be shown on screen
  950.     Call    POSIT             ;  read previous block
  951.     mov     ES,SEGMEM         ;  ES - segment address of block
  952.     mov     di,32767          ;  address of last byte in block
  953.     mov     cx,NREC           ;  number of lines to find
  954.     Call    BKREC             ;  find previous line
  955.     sub     Count,dx          ;  length of rest of block
  956.     jmp     short GOL8        ;  normal return
  957. ;  Previous block < 32768. Positioning to the beginning
  958. GOL5:   xor     cx,cx             ;  high part of offset
  959.     xor     dx,dx             ;  low part of offset
  960.     Call    POSIT             ;  read previous block
  961.     mov     ES,SEGMEM         ;  ES -segment address of block
  962.     mov     di,DXF            ;  address of first line on screen
  963.     mov     cx,NREC           ;  number of lines to find
  964.     Call    BKREC             ;  find previous line
  965.     jc      GOL6              ;  line not found
  966.     sub     Count,dx          ;  length of rest of block
  967.     jmp     short GOL8        ;  normal return
  968. ;  Line to be displayed is located at the start of file
  969. GOL6:   xor     dx,dx             ;  address of first line
  970.     mov     ABLOK,dx          ;  offset from block beginning
  971.     mov     DXB,dx            ;  new offset of line displayed
  972.     mov     DXF,dx            ;  low part of offset  = 0
  973.     mov     CXF,dx            ;  high part of offset  = 0
  974.     RETN                      ;  return to caller
  975. ;======
  976. ;  Two blocks on screen (NB = 2). Previous block has to be read
  977. GOL7:   mov     cx,CXF            ;  high part of offset
  978.     mov     dx,DXF            ;  low part of offset
  979.     sub     dx,DXB            ;  start of previous block (high)
  980.     sbb     cx,0              ;  start of previous (low)
  981.     Call    POSIT             ;  read previous block
  982. ;  Find the line in previous block to be shown as the first line on the screen
  983.     mov     ES,SEGMEM         ;  ES - segment address of block
  984.     mov     di,DXB            ;  address of screen beginning
  985.     mov     cx,NREC           ;  number of lines inserted
  986.     Call    BKREC             ;  find previous line
  987.     sub     Count,dx          ;  length of rest of block
  988. ;  Set up parameters for previous block and exit (AX -length of string
  989. GOL8:   mov     ABLOK,dx          ;  offset from block beginning
  990.     mov     DXB,dx            ;  new offset of line displayed
  991.     sub     DXF,ax            ;  low part of offset
  992.     sbb     CXF,0             ;  high part of offset
  993.     RETN                      ;  return to caller
  994. GOLOW   ENDP
  995. ;***********************************************************
  996. ;
  997. ;  Subroutine for reading the last but one line
  998. ;
  999. ;  The backwards parsing of the block is performed
  1000. ;
  1001. ;  On entry:  ES:DI  - address of last line beginning
  1002. ;             CX     - the number of lines required
  1003. ;
  1004. ;  On return: ES:DX  - address of line found
  1005. ;             AX     - length of lines found
  1006. ;
  1007. ;             CF =0  - all length found successfully
  1008. ;
  1009. ;             CF =1  - required nomber of lines not found
  1010. ;                      in this case CX - number of lines not processed
  1011. ;
  1012. ;***********************************************************
  1013. BKREC   PROC    NEAR
  1014.     xor     ax,ax             ;  record length counter
  1015. BK0:    mov     dx,di             ;  save address
  1016.     dec     di                ;  address of last byte (possibly LF)
  1017.     jl      BK4               ;
  1018. ;  Find the end of last line (the CR and LF pair)
  1019. BK1:    cmp     byte ptr ES:[DI],0Ah ;  LF ?
  1020.     jne     BK2               ;
  1021.     dec     di                ;  address of previous byte
  1022.     jl      BK4               ;
  1023.     inc     ax                ;  modify length counter
  1024. BK2:    cmp     byte ptr ES:[DI],0Dh ;  CR ?
  1025.     jne     BK3               ;
  1026.     dec     di                ;  address of privious byte
  1027.     jl      BK4               ;
  1028.     inc     ax                ;  modify length counter
  1029. ;  Find last line (first LF from the last but one line)
  1030. BK3:    cmp     byte ptr ES:[DI],0Ah ;  LF ?
  1031.     je      BK4               ;
  1032.     dec     di                ;  address of previous byte
  1033.     jl      BK4               ;
  1034.     inc     ax                ;  modify length counter
  1035.     jmp     short BK3         ;  character found, continue cycle
  1036. ;  Modify pthe cycle paramters and analizing rezults
  1037. BK4:    inc     di                ;  address of last line beginning
  1038.     jz      BK5               ;  beginning of file block
  1039.     loop    BK0               ;  continue lines detachment
  1040.     mov     dx,di             ;  address of first line on screen
  1041.     clc                       ;  CF = 0 - successful detachment
  1042.     RETN                      ;  return to caller
  1043. BK5:    stc                       ;  CF = 1 - requested lenes not found
  1044.     RETN                      ;  return to caller
  1045. BKREC   ENDP
  1046. _TEXT   ENDS
  1047. ;-----------------------------------------------------------------------
  1048. ZSEG    SEGMENT  'ZERO'
  1049. ZSEG    ENDS
  1050. ;-----------------------------------------------------------------------
  1051.     END    START
  1052.